package com.yxinsur.imc.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxinsur.imc.business.domain.*;
import com.yxinsur.imc.business.dto.OrderDto;
import com.yxinsur.imc.business.dto.OrderEndCancelSuspensionDto;
import com.yxinsur.imc.business.dto.OrderReceiptRevisitCustomDto;
import com.yxinsur.imc.business.enums.*;
import com.yxinsur.imc.business.events.publisher.OrderCreateEventPublisher;
import com.yxinsur.imc.business.events.publisher.OrderCustomerEventPublisher;
import com.yxinsur.imc.business.excel.OrderTemplate;
import com.yxinsur.imc.business.form.*;
import com.yxinsur.imc.business.mapper.*;
import com.yxinsur.imc.business.service.IImcInsRateService;
import com.yxinsur.imc.business.service.IImcOrderService;
import com.yxinsur.imc.business.vo.*;
import com.yxinsur.imc.common.core.domain.entity.SysOrg;
import com.yxinsur.imc.common.exception.BusinessException;
import com.yxinsur.imc.common.utils.DateUtils;
import com.yxinsur.imc.common.utils.SecurityUtils;
import com.yxinsur.imc.common.utils.StringUtils;
import com.yxinsur.imc.common.utils.bean.MyBeanUtils;
import com.yxinsur.imc.common.validator.Assert;
import com.yxinsur.imc.system.mapper.SysOrgMapper;
import com.yxinsur.imc.system.service.ISysOrgService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 保单Service业务层处理
 *
 * @author imc
 * @date 2021-03-18
 */
@Service
public class ImcOrderServiceImpl extends ServiceImpl<ImcOrderMapper, ImcOrder> implements IImcOrderService {
    private static final Logger logger = LoggerFactory.getLogger(ImcOrderServiceImpl.class);

    @Autowired
    private ImcOrderMapper imcOrderMapper;
    @Autowired
    private ImcOrderPersonMapper imcOrderPersonMapper;
    @Autowired
    private ImcOrderRiskMapper imcOrderRiskMapper;
    @Autowired
    private ImcOrderImgMapper imcOrderImgMapper;
    @Autowired
    private ImcOrderBankInfoMapper imcOrderBankInfoMapper;
    @Autowired
    private ImcBrokerMapper imcBrokerMapper;
    @Autowired
    private ImcTenantMapper imcTenantMapper;
    @Autowired
    private ImcTeamMapper imcTeamMapper;
    @Autowired
    private ImcFeeRateMapper imcFeeRateMapper;
    @Autowired
    private ImcInsSchemeMapper imcInsSchemeMapper;
    @Autowired
    private ImcInsRateMapper imcInsRateMapper;
    @Autowired
    private ImcRepoInsMapper imcRepoInsMapper;
    @Autowired
    private ImcRepoSupplierMapper imcRepoSupplierMapper;
    @Autowired
    private IImcInsRateService imcInsRateService;
    @Autowired
    private SysOrgMapper sysOrgMapper;
    @Autowired
    private ISysOrgService sysOrgService;
    @Autowired
    private OrderCreateEventPublisher orderCreateEventPublisher;
    @Autowired
    private ImcRecnDetailsMapper recnDetailsMapper;
    @Autowired
    private OrderCustomerEventPublisher orderCustomerEventPublisher;

    /**
     * 查询保单列表
     *
     * @param searchForm 保单
     * @return 保单
     */
    @Override
    public List<OrderVo> selectQueryOrderList(OrderSearchForm searchForm) {
        //保单列表
        String[] orderStatusCodes = {OrderStatusCodeEnum.STATUS_20.getCode(), OrderStatusCodeEnum.STATUS_30.getCode(), OrderStatusCodeEnum.STATUS_40.getCode()};
        String authOrgIds = SecurityUtils.getLoginUser().getAuthOrgIds();
        return imcOrderMapper.selectImcOrderList(searchForm, StringUtils.join(orderStatusCodes, ","), authOrgIds, SecurityUtils.getTenantId());
    }

    /**
     * 校验保单号是否唯一
     *
     * @param policyCode 保单号
     * @return 结果
     */
    @Override
    public boolean checkPolicyCodeUnique(String policyCode, Long orderId, Long tenantId) {
        QueryWrapper<ImcOrder> orderQueryWrapper = new QueryWrapper<>();
        if (orderId != null) {
            orderQueryWrapper.ne("id", orderId);
        }
        orderQueryWrapper.eq("policy_code", policyCode);
        orderQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        orderQueryWrapper.eq("tenant_id", tenantId);
        int count = this.imcOrderMapper.selectCount(orderQueryWrapper);
        if (count > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 校验投保单号是否唯一
     *
     * @param proposalCode 投保单号
     * @return 结果
     */
    @Override
    public boolean checkProposalCodeCodeUnique(String proposalCode, Long orderId, Long tenantId) {
        QueryWrapper<ImcOrder> orderQueryWrapper = new QueryWrapper<>();
        if (orderId != null) {
            orderQueryWrapper.ne("id", orderId);
        }
        orderQueryWrapper.eq("proposal_code", proposalCode);
        orderQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        orderQueryWrapper.eq("tenant_id", tenantId);
        int count = this.imcOrderMapper.selectCount(orderQueryWrapper);
        if (count > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 新增保单
     *
     * @param orderData 保单
     * @return 结果
     */
    @Override
    @Transactional
    public void insureOrder(OrderDataForm orderData) {
        logger.info("新增保单...");
        Date date = DateUtils.getNowDate();
        OrderForm orderForm = orderData.getOrder();
        OrderBankInfoForm bankInfoForm = orderData.getBankInfo();
        List<OrderPersonForm> applicantForms = orderData.getApplicants();
        List<OrderPersonForm> insurantForms = orderData.getInsurants();
        List<OrderPersonForm> favourForms = orderData.getFavours();
        List<OrderRiskInputForm> riskForms = orderData.getRisks();
        List<OrderImgForm> imgForms = orderData.getImgs();
        Assert.isBlank(orderForm.getProposalCode(), "投保单号不能为空");
        //基本信息
        ImcOrder order = new ImcOrder();
        BeanUtils.copyProperties(orderForm, order);
        if (checkPolicyCodeUnique(order.getPolicyCode(), null, SecurityUtils.getTenantId())) {
            throw new BusinessException("保单号[ " + order.getPolicyCode() + " ]已存在");
        }
        if (checkProposalCodeCodeUnique(order.getProposalCode(), null, SecurityUtils.getTenantId())) {
            throw new BusinessException("投保单号[ " + order.getProposalCode() + " ]已存在");
        }
        //初始出单代理人
        order.setInitBrokerId(order.getBrokerId());
        order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_10.getCode());
        order.setInsureDate(null);
        order.setEffectiveDate(null);
        order.setAckDate(null);
        order.setCustAckDate(null);
        this.orderSave(order, date, SecurityUtils.getTenantId(), SecurityUtils.getUsername());//保存保单主表信息

        //投保人/被保人/受益人
        this.personSave(applicantForms, insurantForms, favourForms, order, OperationEnum.SAVE, date);

        //影像件
        this.imgSave(imgForms, order, date);

        //银行信息
        this.bankInfoSave(bankInfoForm, order, date);

        //险种信息
        this.riskSave(riskForms, order, date);

        //主表更新
        this.imcOrderMapper.updateById(order);
    }

    /**
     * 保存保单信息
     *
     * @param order
     * @param date
     */
    private void orderSave(ImcOrder order, Date date, Long tenantId, String username) {
        order.setCreateTime(date);
        order.setCreateId(username);
        order.setIsDeleted(IsDeletedEnum.N.getCode());
        order.setTenantId(tenantId);
        this.imcOrderMapper.insert(order);
        //发布录入成功事件
        this.orderCreateEventPublisher.pushlish("保单录入成功", order);
    }

    /**
     * 修改保单
     *
     * @param orderData 保单
     * @return 结果
     */
    @Override
    @Transactional
    public void updateImcOrder(OrderDataForm orderData, OrderStepEnum orderStepEnum) {
        logger.info("批改保单...");
        Date date = DateUtils.getNowDate();
        OrderForm orderForm = orderData.getOrder();
        OrderBankInfoForm bankInfoForm = orderData.getBankInfo();
        List<OrderPersonForm> applicantForms = orderData.getApplicants();
        List<OrderPersonForm> insurantForms = orderData.getInsurants();
        List<OrderPersonForm> favourForms = orderData.getFavours();
        List<OrderRiskInputForm> riskForms = orderData.getRisks();
        List<OrderImgForm> imgForms = orderData.getImgs();

        //基本信息
        ImcOrder order = this.imcOrderMapper.selectById(orderForm.getId());
        BeanUtils.copyProperties(orderForm, order);
        //初始出单代理人
        order.setUpdateTime(date);
        order.setUpdateId(SecurityUtils.getUsername());

        //状态处理
        switch (orderStepEnum) {
            case ACCEPT_INSURE://承保录入
                if (orderForm.getInsureDate() == null) {
                    throw new BusinessException("承保日期不能为空");
                }
                if (StringUtils.isBlank(orderForm.getPolicyCode())) {
                    throw new BusinessException("保单号不能为空");
                }
                order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_20.getCode());
                //承保录入保存人员信息
                ArrayList<OrderPersonForm> personList = new ArrayList<>();
                personList.addAll(applicantForms);
                personList.addAll(insurantForms);
                personList.addAll(favourForms);
                orderCustomerEventPublisher.pushlish("客户信息同步成功",order.getBrokerId(), personList);
                break;
            case ORDER_EDIT:
                break;
        }

        //投被保受益人信息更新(逻辑删除后新增)
        UpdateWrapper<ImcOrderPerson> personUpdateWrapper = new UpdateWrapper<>();
        personUpdateWrapper.set("is_deleted", IsDeletedEnum.Y.getCode());
        personUpdateWrapper.set("update_time", date);
        personUpdateWrapper.set("update_id", SecurityUtils.getUsername());
        personUpdateWrapper.eq("order_id", order.getId());
        personUpdateWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        this.imcOrderPersonMapper.update(null, personUpdateWrapper);
        this.personSave(applicantForms, insurantForms, favourForms, order, OperationEnum.UPDATE, date);

        //银行卡信息更新(逻辑删除后新增)
        UpdateWrapper<ImcOrderBankInfo> bankInfoUpdateWrapper = new UpdateWrapper<>();
        bankInfoUpdateWrapper.set("is_deleted", IsDeletedEnum.Y.getCode());
        bankInfoUpdateWrapper.set("update_time", date);
        bankInfoUpdateWrapper.set("update_id", SecurityUtils.getUsername());
        bankInfoUpdateWrapper.eq("order_id", order.getId());
        bankInfoUpdateWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        this.imcOrderBankInfoMapper.update(null, bankInfoUpdateWrapper);
        this.bankInfoSave(bankInfoForm, order, date);

        //影像件信息更新(逻辑删除后新增)
        UpdateWrapper<ImcOrderImg> imgUpdateWrapper = new UpdateWrapper<>();
        imgUpdateWrapper.set("is_deleted", IsDeletedEnum.Y.getCode());
        imgUpdateWrapper.eq("order_id", order.getId());
        this.imcOrderImgMapper.update(null, imgUpdateWrapper);
        this.imgSave(imgForms, order, date);

        //险种信息更新(逻辑删除后新增)
        UpdateWrapper<ImcOrderRisk> riskUpdateWrapper = new UpdateWrapper<>();
        riskUpdateWrapper.set("is_deleted", IsDeletedEnum.Y.getCode());
        riskUpdateWrapper.eq("order_id", order.getId());
        riskUpdateWrapper.eq("policy_year", 1);//只更首年
        this.imcOrderRiskMapper.update(null, riskUpdateWrapper);
        this.riskSave(riskForms, order, date);

        //主表更新
        this.imcOrderMapper.updateById(order);
    }

    /**
     * 保单人员信息补充
     *
     * @param form            表单数据
     * @param orderPerson     实体
     * @param orderPersonType 保单人员类型：A投保人B被保人C受益人
     * @param operationEnum   操作类型
     * @param date            日期
     * @return
     */
    private ImcOrderPerson orderPersonCopy(ImcOrder order, OrderPersonForm form, ImcOrderPerson orderPerson, String orderPersonType, OperationEnum operationEnum, Date date) {
        switch (operationEnum) {
            case SAVE:
                orderPerson.setCreateTime(date);
                orderPerson.setCreateId(order.getCreateId());
                orderPerson.setTenantId(order.getTenantId());
                break;
            case UPDATE:
                orderPerson.setCreateTime(date);
                orderPerson.setCreateId(order.getCreateId());
                orderPerson.setUpdateTime(date);
                orderPerson.setUpdateId(order.getUpdateId());
                orderPerson.setTenantId(order.getTenantId());
                break;
        }
        BeanUtils.copyProperties(form, orderPerson);
        orderPerson.setIsDeleted(IsDeletedEnum.N.getCode());
        orderPerson.setOrderPersonType(orderPersonType);
        return orderPerson;
    }

    /**
     * 保存投保人被保人受益人信息
     *
     * @param applicantForms
     * @param insurantForms
     * @param favourForms
     * @param order
     * @param operate
     * @param date
     */
    private void personSave(List<OrderPersonForm> applicantForms, List<OrderPersonForm> insurantForms, List<OrderPersonForm> favourForms, ImcOrder order, OperationEnum operate, Date date) {
        boolean hasDefaultApplicant = false;
        OrderPersonForm defaultApplicant = null;//默认投保人
        for (OrderPersonForm applicant : applicantForms) {
            ImcOrderPerson orderPerson = this.orderPersonCopy(order, applicant, new ImcOrderPerson(), OrderPersonTypeEnum.A.getCode(), operate, date);
            orderPerson.setOrderId(order.getId());
            orderPerson.setOrderPersonType(OrderPersonTypeEnum.A.getCode());
            //是否默认
            if (hasDefaultApplicant) {
                orderPerson.setIsDefalut(IsDefaultEnum.N.getCode());
            } else {
                hasDefaultApplicant = true;
                orderPerson.setIsDefalut(IsDefaultEnum.Y.getCode());
                defaultApplicant = applicant;
            }
            this.imcOrderPersonMapper.insert(orderPerson);
        }

        //被保人
        boolean hasDefaultInsurent = false;
        for (OrderPersonForm insurent : insurantForms) {
            String relationWithApplicant = insurent.getRelationWithApplicant();
            if (insurent.getRelationWithApplicant() != null && insurent.getRelationWithApplicant().equals(OrderPersonRelationEnum.本人.name())) {
                BeanUtils.copyProperties(defaultApplicant, insurent);
                insurent.setIsSameApplicant(YesOrNoEnum.Y.name());
                insurent.setRelationWithApplicant(relationWithApplicant);
            }
            ImcOrderPerson orderPerson = this.orderPersonCopy(order, insurent, new ImcOrderPerson(), OrderPersonTypeEnum.B.getCode(), operate, date);
            orderPerson.setOrderId(order.getId());
            //是否默认
            if (hasDefaultInsurent) {
                orderPerson.setIsDefalut(IsDefaultEnum.N.getCode());
            } else {
                hasDefaultInsurent = true;
                orderPerson.setIsDefalut(IsDefaultEnum.Y.getCode());
            }
            this.imcOrderPersonMapper.insert(orderPerson);
        }
        //受益人
        for (OrderPersonForm favour : favourForms) {
            ImcOrderPerson orderPerson = this.orderPersonCopy(order, favour, new ImcOrderPerson(), OrderPersonTypeEnum.C.getCode(), operate, date);
            orderPerson.setOrderId(order.getId());
            this.imcOrderPersonMapper.insert(orderPerson);
        }
    }

    /**
     * 保存支付银行信息
     *
     * @param bankInfoForm
     * @param order
     * @param date
     */
    private void bankInfoSave(OrderBankInfoForm bankInfoForm, ImcOrder order, Date date) {
        ImcOrderBankInfo bankInfo = new ImcOrderBankInfo();
        BeanUtils.copyProperties(bankInfoForm, bankInfo);
        bankInfo.setOrderId(order.getId());
        bankInfo.setCreateTime(date);
        bankInfo.setCreateId(order.getCreateId());
        bankInfo.setUpdateTime(date);
        bankInfo.setUpdateId(order.getUpdateId());
        bankInfo.setTenantId(order.getTenantId());
        bankInfo.setIsDeleted(IsDeletedEnum.N.getCode());
        this.imcOrderBankInfoMapper.insert(bankInfo);
    }

    /**
     * 保存险种信息
     *
     * @param riskForms 险种列表
     * @param order     主保单
     * @param date
     * @return
     */
    private void riskSave(List<OrderRiskInputForm> riskForms, ImcOrder order, Date date) {
        SysOrg org = this.sysOrgMapper.selectOrgById(order.getInputOrgId());
        for (OrderRiskInputForm risk : riskForms) {
            this.saveOrderRisk(risk, order, org, date);
        }
        //更新主表首年规保标保
        this.updateOrderPremAndStandPrem(order);
    }

    /**
     * 保存单个保单险种信息
     *
     * @param risk
     * @param order
     * @param org
     * @param date
     */
    private ImcOrderRisk saveOrderRisk(OrderRiskInputForm risk, ImcOrder order, SysOrg org, Date date) {
        ImcOrderRisk orderRisk = null;
        if (risk.getId() == null) {
            orderRisk = new ImcOrderRisk();
            BeanUtils.copyProperties(risk, orderRisk);
            orderRisk.setOrderId(order.getId());

            orderRisk.setRiskStatusCode(order.getOrderStatusCode());
            orderRisk.setApplyDate(order.getApplyDate());
            orderRisk.setInsureDate(order.getInsureDate());
            orderRisk.setEffectiveDate(order.getEffectiveDate());
            orderRisk.setExpiredDate(order.getExpiredDate());

            //险种获取
            ImcRepoIns ins = this.imcRepoInsMapper.selectById(risk.getRepoInsId());
            orderRisk.setInsCode(ins.getInsCode());
            orderRisk.setRiskName(ins.getRiskName());


            BigDecimal standPrem = orderRisk.getPrem().multiply(risk.getStandRate());
            BigDecimal firstCommission = orderRisk.getPrem().multiply(risk.getCommissionRate());

            orderRisk.setStandRate(risk.getStandRate());
            orderRisk.setStandPrem(standPrem);
            orderRisk.setCommissionRate(risk.getCommissionRate());
            orderRisk.setCommission(firstCommission);
            orderRisk.setSupplierStandRate(risk.getSupplierStandRate());
            orderRisk.setYearScale(risk.getYearScale());

            orderRisk.setPayablePrem(orderRisk.getPrem());
            orderRisk.setPaymentPrem(orderRisk.getPrem());

            orderRisk.setPolicyYear(1l);//默认第一年
            orderRisk.setPayNum(1l);    //默认第一次
            orderRisk.setIsFeeSettled(YesOrNoEnum.N.name());
            orderRisk.setIsCommPaid(YesOrNoEnum.N.name());

            orderRisk.setCreateTime(date);
            orderRisk.setCreateId(order.getCreateId());
            orderRisk.setTenantId(order.getTenantId());
            orderRisk.setIsDeleted(IsDeletedEnum.N.getCode());
            this.imcOrderRiskMapper.insert(orderRisk);
        } else {
            orderRisk = this.imcOrderRiskMapper.selectById(risk.getId());
            BeanUtils.copyProperties(risk, orderRisk);
            //费率重新计算
            BigDecimal standPrem = orderRisk.getPrem().multiply(risk.getStandRate());
            BigDecimal firstCommission = orderRisk.getPrem().multiply(risk.getCommissionRate());

            orderRisk.setStandRate(risk.getStandRate());
            orderRisk.setStandPrem(standPrem);
            orderRisk.setCommissionRate(risk.getCommissionRate());
            orderRisk.setCommission(firstCommission);
            orderRisk.setSupplierStandRate(risk.getSupplierStandRate());
            orderRisk.setYearScale(risk.getYearScale());

            orderRisk.setApplyDate(order.getApplyDate());
            orderRisk.setInsureDate(order.getInsureDate());
            orderRisk.setEffectiveDate(order.getEffectiveDate());
            orderRisk.setAckDate(order.getAckDate());
            orderRisk.setCustAckDate(order.getCustAckDate());

            //应实缴月份
            if (orderRisk.getEffectiveDate() != null) {
                String month = DateUtils.parseDateToStr(DateUtils.YYYY_MM, orderRisk.getEffectiveDate());
                orderRisk.setPayableDate(orderRisk.getEffectiveDate());
                orderRisk.setPayableMonth(month);
                orderRisk.setPaymentDate(orderRisk.getEffectiveDate());
                orderRisk.setPaymentMonth(month);
            }

            orderRisk.setRiskStatusCode(order.getOrderStatusCode());
            orderRisk.setUpdateTime(date);
            orderRisk.setUpdateId(order.getUpdateId());
            orderRisk.setIsDeleted(IsDeletedEnum.N.getCode());
            this.imcOrderRiskMapper.updateById(orderRisk);
        }
        return orderRisk;
    }

    /**
     * 影像件保存
     *
     * @param imgForms
     * @param order
     * @param date
     */
    private void imgSave(List<OrderImgForm> imgForms, ImcOrder order, Date date) {
        if (StringUtils.isNotEmpty(imgForms)) {
            for (OrderImgForm imgForm : imgForms) {
                ImcOrderImg img = new ImcOrderImg();
                BeanUtils.copyProperties(imgForm, img);
                img.setOrderId(order.getId());
                img.setCreateTime(date);
                img.setCreateId(order.getCreateId());
                img.setUpdateTime(date);
                img.setUpdateId(order.getUpdateId());
                img.setTenantId(order.getTenantId());
                img.setIsDeleted(IsDeletedEnum.N.getCode());
                this.imcOrderImgMapper.insert(img);
            }
        }
    }

    /**
     * 新增保单险种
     *
     * @param orderId  保单ID
     * @param riskForm 保单险种数据
     * @return 结果
     */
    @Override
    @Transactional
    public void addOrderRisk(Long orderId, OrderRiskInputForm riskForm) {
        ImcOrderRisk risk = null;
        if (riskForm.getId() == null) {
            risk = this.imcOrderRiskMapper.selectById(riskForm.getCopyId());
        } else {
            risk = this.imcOrderRiskMapper.selectById(riskForm.getId());
        }
        BeanUtils.copyProperties(riskForm, risk);

        BigDecimal standPrem = risk.getPrem().multiply(risk.getStandRate());
        BigDecimal firstCommission = risk.getPrem().multiply(risk.getCommissionRate());

        risk.setStandRate(risk.getStandRate());
        risk.setStandPrem(standPrem);
        risk.setCommissionRate(risk.getCommissionRate());
        risk.setCommission(firstCommission);
        risk.setFeeRate(risk.getFeeRate());

        risk.setPayablePrem(risk.getPrem());
        risk.setPaymentPrem(risk.getPrem());
        //应实缴月份
        if (risk.getPayableDate() != null) {
            risk.setPayableMonth(DateUtils.parseDateToStr(DateUtils.YYYY_MM, risk.getPayableDate()));
        }
        if (risk.getPaymentDate() != null) {
            risk.setPaymentMonth(DateUtils.parseDateToStr(DateUtils.YYYY_MM, risk.getPaymentDate()));
        }
        if (riskForm.getId() == null) {
            //最大缴费次数
            int maxCount = ChargeIntervalEnum.getByKName(risk.getChargeIntervalEnum()).getPayNum();
            QueryWrapper<ImcOrderRisk> maxQueryWrapper = new QueryWrapper<>();
            maxQueryWrapper.eq("order_id", risk.getOrderId());
            maxQueryWrapper.eq("repo_ins_id", risk.getRepoInsId());
            maxQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
            int currCount = this.imcOrderRiskMapper.selectCount(maxQueryWrapper);
            if (currCount >= maxCount) {
                throw new BusinessException("该产品缴费记录已达到最大数量，请勿继续添加");
            } else {
                //校验是否重复
                QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
                riskQueryWrapper.eq("order_id", risk.getOrderId());
                riskQueryWrapper.eq("repo_ins_id", risk.getRepoInsId());
                riskQueryWrapper.eq("pay_num", risk.getPayNum());
                riskQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
                int count = this.imcOrderRiskMapper.selectCount(riskQueryWrapper);
                if (count > 0) {
                    throw new BusinessException("该产品第" + risk.getPayNum() + "次缴费记录已经存在，请勿重复添加");
                } else {
                    risk.setCreateTime(DateUtils.getNowDate());
                    risk.setCreateId(SecurityUtils.getUsername());
                    risk.setId(null);
                    this.imcOrderRiskMapper.insert(risk);
                }
            }
        } else {
            //校验是否重复
            QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
            riskQueryWrapper.ne("id", risk.getId());
            riskQueryWrapper.eq("order_id", risk.getOrderId());
            riskQueryWrapper.eq("repo_ins_id", risk.getRepoInsId());
            riskQueryWrapper.eq("pay_num", risk.getPayNum());
            riskQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
            int count = this.imcOrderRiskMapper.selectCount(riskQueryWrapper);
            if (count > 0) {
                throw new BusinessException("该产品第" + risk.getPayNum() + "次缴费记录已经存在，请检查");
            } else {
                risk.setUpdateTime(DateUtils.getNowDate());
                risk.setUpdateId(SecurityUtils.getUsername());
                this.imcOrderRiskMapper.updateById(risk);
            }
        }
        //更新保单主表首年规保和标保
        ImcOrder order = this.imcOrderMapper.selectById(orderId);
        this.updateOrderPremAndStandPrem(order);
    }

    /**
     * 根据risk更新order的首年规保和首年标保
     *
     * @param order
     */
    public void updateOrderPremAndStandPrem(ImcOrder order) {
        QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
        riskQueryWrapper.eq("order_id", order.getId());
        riskQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        riskQueryWrapper.eq("policy_year", 1);//首年数据
        List<ImcOrderRisk> risks = this.imcOrderRiskMapper.selectList(riskQueryWrapper);
        BigDecimal firstPrem = BigDecimal.ZERO;
        BigDecimal standPrem = BigDecimal.ZERO;
        for (ImcOrderRisk risk : risks) {
            firstPrem = firstPrem.add(risk.getPrem());
            standPrem = standPrem.add(risk.getStandPrem());
        }
        order.setFirstPrem(firstPrem);
        order.setStandPrem(standPrem);
        this.imcOrderMapper.updateById(order);
    }

    /**
     * 保单数据导入
     *
     * @param inputOrgIdNotInUse 已弃用，机构ID 取保单代理人所在机构
     * @param orderList
     * @param isUpdateSupport    是否更新支持，如果已存在，则进行更新数据
     * @return
     */
    @Override
    @Transactional
    public String importOrder(Long inputOrgIdNotInUse, Long repoSupplierId, List<OrderTemplate> orderList, Boolean isUpdateSupport) {
        if (StringUtils.isNull(orderList) || orderList.size() == 0) {
            throw new BusinessException("导入保单数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<OrderTemplate> validList = new ArrayList<>();
        Long tenantId = SecurityUtils.getTenantId();
        //校验数据
        for (OrderTemplate template : orderList) {
            if (StringUtils.isNotBlank(template.getIndex())) {
                StringBuffer errorMsg = new StringBuffer();
                //必填项
                if (StringUtils.isBlank(template.getProposalCode())) {
                    errorMsg.append("投保单号不能为空；");
                } else {
                    if (checkProposalCodeCodeUnique(template.getProposalCode(), null, tenantId)) {
                        errorMsg.append("投保单号[" + template.getProposalCode() + "]在系统中已存在；");
                    }
                }
                if (StringUtils.isBlank(template.getPolicyCode())) {
                    errorMsg.append("保单号不能为空；");
                } else {
                    if (checkPolicyCodeUnique(template.getPolicyCode(), null, tenantId)) {
                        errorMsg.append("保单号[" + template.getPolicyCode() + "]在系统中已存在；");
                    }
                }
                if (template.getApplyDate() == null) {
                    errorMsg.append("投保日期不能为空；");
                }
                if (template.getInsureDate() == null) {
                    errorMsg.append("承保日期不能为空；");
                }
                if (template.getEffectiveDate() == null) {
                    errorMsg.append("生效日期不能为空；");
                }
                if (StringUtils.isBlank(template.getInsCode())) {
                    errorMsg.append("险种代码不能为空；");
                }
                if (template.getPrem() == null) {
                    errorMsg.append("险种保费-首年不能为空；");
                }
                if (StringUtils.isBlank(template.getCoveragePeriodEnum())) {
                    errorMsg.append("保障年期类型不能为空；");
                }
                if (StringUtils.isBlank(template.getCoveragePeriodValue())) {
                    errorMsg.append("保障期限不能为空；");
                }
                if (StringUtils.isBlank(template.getChargePeriodEnum())) {
                    errorMsg.append("缴费年期类型不能为空；");
                }
                if (StringUtils.isBlank(template.getChargePeriodValue())) {
                    errorMsg.append("缴费期限不能为空；");
                }
                if (StringUtils.isBlank(template.getFullNameApplicant())) {
                    errorMsg.append("投保人姓名不能为空；");
                }
                if (StringUtils.isBlank(template.getRelationWithApplicant())) {
                    errorMsg.append("与投保人关系不能为空；");
                }
                if (StringUtils.isBlank(template.getIsLegalBeneficiary())) {
                    errorMsg.append("是否法定受益人不能为空；");
                }
                if (StringUtils.isNotBlank(template.getBenefitOrderBeneficiary1()) && !StringUtils.isNumeric(template.getBenefitOrderBeneficiary1())) {
                    errorMsg.append("受益人1受益顺序必须为整数类型；");
                }
                if (StringUtils.isNotBlank(template.getBenefitOrderBeneficiary2()) && !StringUtils.isNumeric(template.getBenefitOrderBeneficiary2())) {
                    errorMsg.append("受益人2受益顺序必须为整数类型；");
                }
                if (StringUtils.isNotBlank(template.getBenefitOrderBeneficiary3()) && !StringUtils.isNumeric(template.getBenefitOrderBeneficiary3())) {
                    errorMsg.append("受益人3受益顺序必须为整数类型；");
                }
                if (StringUtils.isNotBlank(template.getBenefitRateBeneficiary1()) && !StringUtils.isNumeric(template.getBenefitRateBeneficiary1())) {
                    errorMsg.append("受益人1收益比例必须为整数类型；");
                }
                if (StringUtils.isNotBlank(template.getBenefitRateBeneficiary2()) && !StringUtils.isNumeric(template.getBenefitRateBeneficiary2())) {
                    errorMsg.append("受益人2收益比例必须为整数类型；");
                }
                if (StringUtils.isNotBlank(template.getBenefitRateBeneficiary3()) && !StringUtils.isNumeric(template.getBenefitRateBeneficiary3())) {
                    errorMsg.append("受益人3收益比例必须为整数类型；");
                }
                if (StringUtils.isBlank(template.getPensionAge())) {
                    template.setPensionAge(null);
                }
                if (StringUtils.isBlank(template.getSettleOrgName())) {
                    errorMsg.append("结算机构名称不能为空；");
                } else {
                    SysOrg sysOrg = sysOrgMapper.selectOrgByOrgName(template.getSettleOrgName(), SecurityUtils.getTenantId());
                    if (sysOrg == null) {
                        errorMsg.append("结算机构名称[" + template.getSettleOrgName() + "]在系统中不存在；");
                    }
                }
                if (errorMsg.length() > 0) {
                    errorMsg.insert(0, "序号：" + template.getIndex() + ",");
                    errorMsg.append("\n");
                    failureNum++;
                } else {
                    validList.add(template);
                }
                failureMsg.append(errorMsg);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：\n");
            throw new BusinessException(failureMsg.toString());
        }

        //分组数据合并处理
        Map<String, List<OrderTemplate>> map = validList.stream().collect(Collectors.groupingBy(x -> x.getProposalCode()));
        logger.info("导入分组以后的保单数据：" + map);
        Date date = DateUtils.getNowDate();
        String username = SecurityUtils.getUsername() + "-import";
        ImcRepoSupplier repoSupplier = this.imcRepoSupplierMapper.selectById(repoSupplierId);
        //遍历保单
        for (Map.Entry<String, List<OrderTemplate>> entry : map.entrySet()) {

            successNum++;
            String proposalCode = entry.getKey();//投保单号
            List<OrderTemplate> risks = entry.getValue();//保单及险种信息
            OrderTemplate template = risks.get(0);

            //校验同单号保单是否重复，保单号+险种编码+年期
            for (int i = 0; i < risks.size(); i++) {
                OrderTemplate order1 = risks.get(i);
                for (int j = i + 1; j < risks.size(); j++) {
                    OrderTemplate order2 = risks.get(j);
                    if (order1.getProposalCode().equals(order2.getProposalCode())
                            && order1.getInsCode().equals(order2.getInsCode())
                            && order1.getChargePeriodValue().equals(order2.getChargePeriodValue())) {
                        throw new BusinessException("序号为【" + order1.getIndex() + "】的行和序号为【" + order2.getIndex() + "】的行的保单数据（保单号：" + order1.getPolicyCode() + "）重复，请检查确认！");
                    }
                }
            }

            //保存订单数据
            ImcOrder order = new ImcOrder();
            BeanUtils.copyProperties(template, order);
            order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_20.getCode());
            order.setRepoSupplierId(repoSupplierId);
            Long inputOrgId = null;
            //代理人信息处理(可以为空，有值必须有效)
            if (StringUtils.isNotBlank(template.getBrokerCode())) {
                ImcBroker broker = this.imcBrokerMapper.selectImcBrokerByCode(template.getBrokerCode(), SecurityUtils.getTenantId());
                Assert.isNull(broker, "序号为【" + template.getIndex() + "】行数据中保单中的代理人工号无效，在系统中不存在；");
                order.setBrokerId(broker.getId());
                order.setInitBrokerId(broker.getId());
                ImcTeam team = this.imcTeamMapper.selectImcTeamById(broker.getTeamId());
                if (team != null) {
                    inputOrgId = team.getOrgId();
                }
            }
            order.setInputOrgId(inputOrgId);
            //结算机构信息处理
            SysOrg sysOrg = sysOrgMapper.selectOrgByOrgName(template.getSettleOrgName(), SecurityUtils.getTenantId());
            order.setSettleOrgId(sysOrg.getOrgId());
            //保存
            this.orderSave(order, date, tenantId, username);

            //银行数据
            ImcOrderBankInfo bankInfo = new ImcOrderBankInfo();
            BeanUtils.copyProperties(template, bankInfo);
            bankInfo.setOrderId(order.getId());
            bankInfo.setCreateTime(date);
            bankInfo.setCreateId(username);
            bankInfo.setIsDeleted(IsDeletedEnum.N.getCode());
            bankInfo.setTenantId(SecurityUtils.getTenantId());
            this.imcOrderBankInfoMapper.insert(bankInfo);

            //投保人
            ImcOrderPerson applicant = new ImcOrderPerson();
            applicant.setOrderId(order.getId());
            applicant.setOrderPersonType(OrderPersonTypeEnum.A.getCode());
            applicant.setFullName(template.getFullNameApplicant());
            applicant.setGender(template.getGenderApplicant());
            applicant.setOccName(template.getOccNameApplicant());
            applicant.setCertiType(template.getCertiTypeApplicant());
            applicant.setCertiCode(template.getCertiCodeApplicant());
            applicant.setBirthday(template.getBirthdayApplicant());
            applicant.setCertiExpiryDate(template.getCertiExpiryDateApplicant());
            applicant.setMobile(template.getMobileApplicant());
            applicant.setProvince(template.getProvinceApplicant());
            applicant.setCity(template.getCityApplicant());
            applicant.setCounty(template.getCountyApplicant());
            applicant.setMailAddr(template.getMailAddrApplicant());
            applicant.setIncome(template.getIncomeApplicant());
            applicant.setHeight(template.getHeightApplicant());
            applicant.setWeight(template.getWeightApplicant());
            applicant.setCreateTime(date);
            applicant.setCreateId(username);
            applicant.setIsDeleted(IsDeletedEnum.N.getCode());
            applicant.setTenantId(SecurityUtils.getTenantId());
            this.imcOrderPersonMapper.insert(applicant);

            //被保人
            ImcOrderPerson insurant = new ImcOrderPerson();
            if (template.getRelationWithApplicant().equals(OrderPersonRelationEnum.本人.name())) {
                BeanUtils.copyProperties(applicant, insurant);
                insurant.setIsSameApplicant(YesOrNoEnum.Y.name());
                insurant.setId(null);
            } else {
                insurant.setOrderId(order.getId());
                insurant.setFullName(template.getFullNameInsurant());
                insurant.setGender(template.getGenderInsurant());
                insurant.setOccName(template.getOccNameInsurant());
                insurant.setCertiType(template.getCertiTypeInsurant());
                insurant.setCertiCode(template.getCertiCodeInsurant());
                insurant.setBirthday(template.getBirthdayInsurant());
                insurant.setCertiExpiryDate(template.getCertiExpiryDateInsurant());
                insurant.setMobile(template.getMobileInsurant());
                insurant.setProvince(template.getProvinceInsurant());
                insurant.setCity(template.getCityInsurant());
                insurant.setCounty(template.getCountyInsurant());
                insurant.setMailAddr(template.getMailAddrInsurant());
                insurant.setIncome(template.getIncomeInsurant());
                insurant.setHeight(template.getHeightInsurant());
                insurant.setWeight(template.getWeightInsurant());
            }
            insurant.setRelationWithApplicant(template.getRelationWithApplicant());
            insurant.setOrderPersonType(OrderPersonTypeEnum.B.getCode());
            insurant.setCreateTime(date);
            insurant.setCreateId(username);
            insurant.setIsDeleted(IsDeletedEnum.N.getCode());
            insurant.setTenantId(SecurityUtils.getTenantId());
            this.imcOrderPersonMapper.insert(insurant);

            //受益人
            ImcOrderPerson beneficiary1 = new ImcOrderPerson();
            beneficiary1.setOrderId(order.getId());
            beneficiary1.setIsLegalBeneficiary(template.getIsLegalBeneficiary());
            beneficiary1.setFullName(template.getFullNameBeneficiary1());
            beneficiary1.setOrderPersonType(OrderPersonTypeEnum.C.getCode());
            beneficiary1.setGender(template.getGenderBeneficiary1());
            beneficiary1.setCertiType(template.getCertiTypeBeneficiary1());
            beneficiary1.setCertiCode(template.getCertiCodeBeneficiary1());
            beneficiary1.setBirthday(template.getBirthdayBeneficiary1());
            beneficiary1.setBenefitOrder(StringUtils.isBlank(template.getBenefitOrderBeneficiary1()) ? null : template.getBenefitOrderBeneficiary1());
            beneficiary1.setBenefitRate(StringUtils.isBlank(template.getBenefitRateBeneficiary1()) ? null : template.getBenefitRateBeneficiary1());
            beneficiary1.setRelationWithInsurant(template.getRelationWithInsurantBeneficiary1());
            beneficiary1.setCreateTime(date);
            beneficiary1.setCreateId(username);
            beneficiary1.setIsDeleted(IsDeletedEnum.N.getCode());
            beneficiary1.setTenantId(SecurityUtils.getTenantId());
            this.imcOrderPersonMapper.insert(beneficiary1);
            if (StringUtils.isNotBlank(template.getFullNameBeneficiary2())) {
                ImcOrderPerson beneficiary2 = new ImcOrderPerson();
                beneficiary2.setOrderId(order.getId());
                beneficiary2.setOrderPersonType(OrderPersonTypeEnum.C.getCode());
                beneficiary2.setFullName(template.getFullNameBeneficiary2());
                beneficiary2.setGender(template.getGenderBeneficiary2());
                beneficiary2.setCertiType(template.getCertiTypeBeneficiary2());
                beneficiary2.setCertiCode(template.getCertiCodeBeneficiary2());
                beneficiary2.setBirthday(template.getBirthdayBeneficiary2());
                beneficiary2.setBenefitOrder(StringUtils.isBlank(template.getBenefitOrderBeneficiary2()) ? null : template.getBenefitOrderBeneficiary2());
                beneficiary2.setBenefitRate(StringUtils.isBlank(template.getBenefitRateBeneficiary2()) ? null : template.getBenefitRateBeneficiary2());
                beneficiary2.setRelationWithInsurant(template.getRelationWithInsurantBeneficiary2());
                beneficiary2.setCreateTime(date);
                beneficiary2.setCreateId(username);
                beneficiary2.setIsDeleted(IsDeletedEnum.N.getCode());
                beneficiary2.setTenantId(SecurityUtils.getTenantId());
                this.imcOrderPersonMapper.insert(beneficiary2);
            }
            if (StringUtils.isNotBlank(template.getFullNameBeneficiary3())) {
                ImcOrderPerson beneficiary3 = new ImcOrderPerson();
                beneficiary3.setOrderId(order.getId());
                beneficiary3.setOrderPersonType(OrderPersonTypeEnum.C.getCode());
                beneficiary3.setFullName(template.getFullNameBeneficiary3());
                beneficiary3.setGender(template.getGenderBeneficiary3());
                beneficiary3.setCertiType(template.getCertiTypeBeneficiary3());
                beneficiary3.setCertiCode(template.getCertiCodeBeneficiary3());
                beneficiary3.setBirthday(template.getBirthdayBeneficiary3());
                beneficiary3.setBenefitOrder(StringUtils.isBlank(template.getBenefitOrderBeneficiary3()) ? null : template.getBenefitOrderBeneficiary3());
                beneficiary3.setBenefitRate(StringUtils.isBlank(template.getBenefitRateBeneficiary3()) ? null : template.getBenefitRateBeneficiary3());
                beneficiary3.setRelationWithInsurant(template.getRelationWithInsurantBeneficiary3());
                beneficiary3.setCreateTime(date);
                beneficiary3.setCreateId(username);
                beneficiary3.setIsDeleted(IsDeletedEnum.N.getCode());
                beneficiary3.setTenantId(SecurityUtils.getTenantId());
                this.imcOrderPersonMapper.insert(beneficiary3);
            }

            //机构信息获取
            SysOrg org = this.sysOrgMapper.selectOrgById(inputOrgId);
            SysOrg settleOrg = this.sysOrgMapper.selectOrgByOrgName(template.getSettleOrgName(),SecurityUtils.getTenantId());
            //险种信息
            BigDecimal totalFirstPrem = BigDecimal.ZERO;
            BigDecimal totalStandPrem = BigDecimal.ZERO;
            for (OrderTemplate item : risks) {
                ImcOrderRisk risk = new ImcOrderRisk();
                BeanUtils.copyProperties(item, risk);
                risk.setOrderId(order.getId());
                risk.setPolicyYear(1L);//默认第一年
                risk.setPayNum(1L);    //默认第一次

                //险种获取
                QueryWrapper<ImcRepoIns> repoInsQueryWrapper = new QueryWrapper<>();
                repoInsQueryWrapper.eq("ins_code", item.getInsCode());
                repoInsQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
                repoInsQueryWrapper.eq("repo_supplier_id", repoSupplierId);
                List<ImcRepoIns> insList = this.imcRepoInsMapper.selectList(repoInsQueryWrapper);
                ImcRepoIns ins = null;
                if (insList.size() == 1) {
                    ins = insList.get(0);
                    risk.setRepoInsId(ins.getId());
                    risk.setRiskName(ins.getRiskName());
                } else {
                    throw new BusinessException("序号为【" + item.getIndex() + "】行数据中险种代码 [" + item.getInsCode() + "] 在系统中匹配不到唯一数据，请检查确认；");
                }
                if (repoSupplierId != ins.getRepoSupplierId()) {
                    throw new BusinessException("序号为【" + item.getIndex() + "】行的险种 [" + ins.getRiskName() + "] 不是 [" + repoSupplier.getSupplierName() + "] 下的产品，请检查确认；");
                }

                //方案
                if (StringUtils.isNotBlank(item.getScheme())) {
                    QueryWrapper<ImcInsScheme> schemeQueryWrapper = new QueryWrapper<>();
                    schemeQueryWrapper.eq("ins_scheme_value", item.getScheme());
                    schemeQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
                    List<ImcInsScheme> schemeList = this.imcInsSchemeMapper.selectList(schemeQueryWrapper);
                    if (schemeList.size() > 0) {
                        ImcInsScheme scheme = schemeList.get(0);
                        risk.setInsSchemeId(scheme.getId());
                    } else {
                        throw new BusinessException("序号为【" + item.getIndex() + "】行数据中方案名称在系统中不存在，请检查确认；");
                    }
                }
                //折标率获取
                OrderRiskRateVo feeA = null;
                feeA = this.getInsRate(ins, risk, settleOrg);
                //对佣金 折标 做必填校验
                if (!feeA.isHasCommissionRate() || !feeA.isHasStandRate()) {
                    throw new BusinessException("序号为【" + item.getIndex() + "】行" + "佣金费率或中介折标费率错误" + "，请检查确认；");
                }

                BigDecimal standPrem = item.getPrem().multiply(feeA.getStandRate());
                BigDecimal firstCommission = item.getPrem().multiply(feeA.getCommissionRate());

                risk.setStandRate(feeA.getStandRate());
                risk.setStandPrem(standPrem);
                risk.setCommissionRate(feeA.getCommissionRate());
                risk.setCommission(firstCommission);
                risk.setSupplierStandRate(feeA.getSupplierStandRate());
                risk.setYearScale(feeA.getYearScale());

                //应实收
                risk.setPayablePrem(risk.getPrem());
                risk.setPaymentPrem(risk.getPrem());
                //应实缴月份
                if (risk.getEffectiveDate() != null) {
                    String month = DateUtils.parseDateToStr(DateUtils.YYYY_MM, risk.getEffectiveDate());
                    risk.setPayableDate(risk.getEffectiveDate());
                    risk.setPayableMonth(month);
                    risk.setPaymentDate(risk.getEffectiveDate());
                    risk.setPaymentMonth(month);
                }
                risk.setApplyDate(order.getApplyDate());
                risk.setInsureDate(order.getInsureDate());
                risk.setEffectiveDate(order.getEffectiveDate());
                risk.setExpiredDate(order.getExpiredDate());

                risk.setIsFeeSettled(YesOrNoEnum.N.name());
                risk.setIsCommPaid(YesOrNoEnum.N.name());

                risk.setRiskStatusCode(order.getOrderStatusCode());
                risk.setCreateTime(date);
                risk.setCreateId(username);
                risk.setIsDeleted(IsDeletedEnum.N.getCode());
                risk.setTenantId(SecurityUtils.getTenantId());
                this.imcOrderRiskMapper.insert(risk);

                totalFirstPrem = totalFirstPrem.add(item.getPrem());
                totalStandPrem = totalStandPrem.add(standPrem);
            }
            order.setFirstPrem(totalFirstPrem);
            order.setStandPrem(totalStandPrem);
            this.imcOrderMapper.updateById(order);
        }

        successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        return successMsg.toString();
    }

    //获取费率
    private OrderRiskRateVo getInsRate(ImcRepoIns ins, ImcOrderRisk risk, SysOrg org) {
        logger.info("根据条件获取费率...");
        //校验有效时间时间
        Date checkDate = risk.getInsureDate() == null ? risk.getApplyDate() : risk.getInsureDate();
        OrderRiskForm riskForm = new OrderRiskForm();
        BeanUtils.copyProperties(risk, riskForm);
        riskForm.setApplyDate(checkDate);
        riskForm.setRepoInsId(ins.getId());
        riskForm.setSettleOrgId(org.getOrgId());
        risk.setPensionAge(risk.getPensionAge());
        return imcInsRateService.getRates(riskForm);

    }

    /**
     * 查询保单录入列表
     *
     * @param searchForm 保单
     * @return 保单集合
     */
    @Override
    public List<OrderVo> selectInputOrderList(OrderSearchForm searchForm) {
        //保单列表
        String[] orderStatusCodes = {OrderStatusCodeEnum.STATUS_10.getCode()};
        String authOrgIds = SecurityUtils.getLoginUser().getAuthOrgIds();
        return imcOrderMapper.selectImcOrderList(searchForm, StringUtils.join(orderStatusCodes, ","), authOrgIds, SecurityUtils.getTenantId());
    }

    /**
     * 查询保单撤销列表
     *
     * @param searchForm 保单
     * @return 保单集合
     */
    @Override
    public List<OrderVo> selectCancelOrderList(OrderSearchForm searchForm) {
        //保单列表
        String[] orderStatusCodes = {OrderStatusCodeEnum.STATUS_10.getCode()};
        String authOrgIds = SecurityUtils.getLoginUser().getAuthOrgIds();
        return imcOrderMapper.selectImcOrderList(searchForm, StringUtils.join(orderStatusCodes, ","), authOrgIds, SecurityUtils.getTenantId());
    }

    /**
     * 查询保单回执列表
     *
     * @param searchForm 保单
     * @return 保单集合
     */
    @Override
    public List<OrderVo> selectReceiptOrderList(OrderSearchForm searchForm) {
        //保单列表
        String[] orderStatusCodes = {OrderStatusCodeEnum.STATUS_20.getCode()};
        String authOrgIds = SecurityUtils.getLoginUser().getAuthOrgIds();
        searchForm.setIsReceipt(YesOrNoEnum.N.name());
        return imcOrderMapper.selectImcOrderList(searchForm, StringUtils.join(orderStatusCodes, ","), authOrgIds, SecurityUtils.getTenantId());
    }

    /**
     * 查询保单终止列表
     *
     * @param searchForm 保单
     * @return 保单集合
     */
    @Override
    public List<OrderVo> selectEndOrderList(OrderSearchForm searchForm) {
        //保单列表
        String[] orderStatusCodes = {OrderStatusCodeEnum.STATUS_20.getCode()};
        String authOrgIds = SecurityUtils.getLoginUser().getAuthOrgIds();
        return imcOrderMapper.selectImcOrderList(searchForm, StringUtils.join(orderStatusCodes, ","), authOrgIds, SecurityUtils.getTenantId());
    }

    /**
     * 查询非年交模块保单列表
     *
     * @param searchForm 保单
     * @return 保单集合
     */
    @Override
    public List<OrderVo> selectNonAnnualOrderList(OrderSearchForm searchForm) {
        //保单列表
        String[] orderStatusCodes = {OrderStatusCodeEnum.STATUS_20.getCode()};
        searchForm.setIsNonAnnual(YesOrNoEnum.Y.name());
        String authOrgIds = SecurityUtils.getLoginUser().getAuthOrgIds();
        return imcOrderMapper.selectImcOrderList(searchForm, StringUtils.join(orderStatusCodes, ","), authOrgIds, SecurityUtils.getTenantId());
    }

    /**
     * 查询保单险种列表
     *
     * @param orderId 保单ID
     * @return 保单集合
     */
    @Override
    public List<OrderRiskVo> selectOrderRiskList(Long orderId) {
        return this.imcOrderRiskMapper.selectOrderRisksList(orderId, 0, SecurityUtils.getTenantId(), new RenewalOrderSearchForm());
    }

    /**
     * 查询续期保单险种列表
     *
     * @param searchForm 查询条件
     * @return 保单集合
     */
    @Override
    public List<OrderRiskVo> selectRenewalRiskList(RenewalOrderSearchForm searchForm) {
        //查询续期
        return this.imcOrderRiskMapper.selectOrderRisksList(null, 1, SecurityUtils.getTenantId(), searchForm);
    }

    /**
     * 保单撤销
     *
     * @param cancelForm 保单
     * @return 结果
     */
    @Override
    public void cancelImcOrder(OrderCancelForm cancelForm) {
        logger.info("保单撤销操作：{}", cancelForm.toString());
        Assert.isNull(cancelForm.getOrderId(), "orderId不允许为空，无法与保单关联");
        ImcOrder order = this.checkOrderByOrderId(cancelForm.getOrderId());
        order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_30.getCode());
        order.setCancelDate(DateUtils.getNowDate());
        order.setCancelCauseNote(cancelForm.getCancelCauseNote());
        order.setPolicyCode("CX:" + order.getPolicyCode());
        order.setProposalCode("CX:" + order.getProposalCode());
        order.setUpdateId(SecurityUtils.getUsername());
        order.setUpdateTime(DateUtils.getNowDate());
        this.imcOrderMapper.updateById(order);

        //险种状态更新
        this.updateRiskStatusCode(order.getId(), order.getOrderStatusCode());
    }

    /**
     * 保单回执
     *
     * @param receiptForm 保单
     * @return 结果
     */
    @Override
    public void receiptImcOrder(OrderReceiptForm receiptForm) {
        logger.info("保单回执操作：{}", receiptForm.toString());
        Assert.isNull(receiptForm.getOrderId(), "orderId不允许为空，无法与保单关联");
        ImcOrder order = this.checkOrderByOrderId(receiptForm.getOrderId());
        order.setAckDate(receiptForm.getAckDate());
        order.setCustAckDate(receiptForm.getCustAckDate());
        order.setUpdateId(SecurityUtils.getUsername());
        order.setUpdateTime(DateUtils.getNowDate());
        this.imcOrderMapper.updateById(order);
    }

    /**
     * 保单终止
     *
     * @param endForm 保单
     * @return 结果
     */
    @Override
    @Transactional
    public void endImcOrder(OrderEndForm endForm) {
        logger.info("保单终止操作：{}", endForm.toString());
        Assert.isNull(endForm.getOrderId(), "orderId不允许为空，无法与保单关联");
        ImcOrder order = this.checkOrderByOrderId(endForm.getOrderId());
        order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_40.getCode());
        if (endForm.getEndCause().equals(EndCauseEnum.A.name())) {
            order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_30.getCode());
            order.setCancelDate(endForm.getEndDate());
            order.setCancelCauseNote(endForm.getEndCauseNote());
        }
        order.setEndDate(endForm.getEndDate());
        order.setEndCause(endForm.getEndCause());
        order.setEndCauseNote(endForm.getEndCauseNote());
        order.setUpdateId(SecurityUtils.getUsername());
        order.setUpdateTime(DateUtils.getNowDate());
        this.imcOrderMapper.updateById(order);

        //险种状态更新
        this.updateRiskStatusCode(order.getId(), order.getOrderStatusCode());
    }

    /**
     * 保单险种状态修改
     */
    public void updateRiskStatusCode(Long orderId, String riskStatusCode) {
        QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
        riskQueryWrapper.eq("order_id", orderId);
        riskQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        List<ImcOrderRisk> risks = this.imcOrderRiskMapper.selectList(riskQueryWrapper);
        String username = SecurityUtils.getUsername();
        Date date = DateUtils.getNowDate();
        for (ImcOrderRisk risk : risks) {
            risk.setRiskStatusCode(riskStatusCode);
            risk.setUpdateId(username);
            risk.setUpdateTime(date);
            this.imcOrderRiskMapper.updateById(risk);
        }
    }

    /**
     * 保单险种状态修改
     */
    public void apiUpdateRiskStatusCode(Long orderId, String riskStatusCode) {
        QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
        riskQueryWrapper.eq("order_id", orderId);
        riskQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        List<ImcOrderRisk> risks = this.imcOrderRiskMapper.selectList(riskQueryWrapper);
        Date date = DateUtils.getNowDate();
        for (ImcOrderRisk risk : risks) {
            risk.setRiskStatusCode(riskStatusCode);
            risk.setUpdateId("API");
            risk.setUpdateTime(date);
            this.imcOrderRiskMapper.updateById(risk);
        }
    }

    /**
     * 险种终止
     *
     * @param riskEndForm 险种
     * @return 结果
     */
    @Override
    public void endImcOrderRisk(OrderRiskEndForm riskEndForm) {
        ImcOrderRisk risk = this.imcOrderRiskMapper.selectById(riskEndForm.getOrderRiskId());
        Assert.isNull(risk, "传参有误，险种信息不存在");
        QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
        riskQueryWrapper.eq("order_id", risk.getOrderId());
        riskQueryWrapper.eq("repo_ins_id", risk.getRepoInsId());
        riskQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        List<ImcOrderRisk> list = this.imcOrderRiskMapper.selectList(riskQueryWrapper);
        String username = SecurityUtils.getUsername();
        Date date = DateUtils.getNowDate();
        for (ImcOrderRisk orderRisk : list) {
            orderRisk.setEndCause(riskEndForm.getEndCause());
            orderRisk.setEndCauseNote(riskEndForm.getEndCauseNote());
            orderRisk.setEndDate(riskEndForm.getEndDate());
            orderRisk.setRiskStatusCode(OrderStatusCodeEnum.STATUS_40.getCode());
            orderRisk.setUpdateTime(date);
            orderRisk.setUpdateId(username);
            this.imcOrderRiskMapper.updateById(orderRisk);
        }
    }

    /**
     * 险种豁免
     *
     * @param riskWaiverForm 险种
     * @return 结果
     */
    @Override
    @Transactional
    public void waiverImcOrderRisk(OrderRiskWaiverForm riskWaiverForm) {
        ImcOrderRisk risk = this.imcOrderRiskMapper.selectById(riskWaiverForm.getOrderRiskId());
        Assert.isNull(risk, "传参有误，险种信息不存在");

        QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
        riskQueryWrapper.eq("order_id", risk.getOrderId());
        riskQueryWrapper.eq("repo_ins_id", risk.getRepoInsId());
        riskQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        List<ImcOrderRisk> list = this.imcOrderRiskMapper.selectList(riskQueryWrapper);
        String username = SecurityUtils.getUsername();
        Date date = DateUtils.getNowDate();
        for (ImcOrderRisk orderRisk : list) {
            orderRisk.setWaiverCause(riskWaiverForm.getWaiverCause());
            orderRisk.setWaiverDate(riskWaiverForm.getWaiverDate());
            orderRisk.setIsExempted(YesOrNoEnum.Y.getCode());
            orderRisk.setUpdateTime(DateUtils.getNowDate());
            orderRisk.setUpdateId(SecurityUtils.getUsername());
            this.imcOrderRiskMapper.updateById(orderRisk);
        }
    }

    /**
     * 保单详情查询
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderDetailVo getByOrderId(Long orderId) {
        ImcOrder order = this.imcOrderMapper.selectById(orderId);
        Assert.isNull(order, "查不到该保单信息");
        OrderDetailVo detailVo = new OrderDetailVo();
        if (SecurityUtils.getTenantId().equals(order.getTenantId())) {
            //保单基本信息
            OrderVo orderVo = new OrderVo();
            BeanUtils.copyProperties(order, orderVo);
            ImcBroker serviceBroker = this.imcBrokerMapper.selectById(order.getBrokerId());
            orderVo.setBrokerId(serviceBroker.getId());
            orderVo.setServiceBrokerCode(serviceBroker.getBrokerCode());
            orderVo.setServiceBrokerName(serviceBroker.getFullName());
            ImcBroker issueBroker = this.imcBrokerMapper.selectById(order.getInitBrokerId());
            orderVo.setInitBrokerId(issueBroker.getId());
            orderVo.setIssueBrokerCode(issueBroker.getBrokerCode());
            orderVo.setIssueBrokerName(issueBroker.getFullName());
            if (order.getInputOrgId() != null) {
                SysOrg org = this.sysOrgMapper.selectOrgById(order.getInputOrgId());
                orderVo.setInputOrgName(org.getOrgName());
            }
            if (order.getSettleOrgId() != null) {
                SysOrg settleOrg = this.sysOrgMapper.selectOrgById(order.getSettleOrgId());
                orderVo.setSettleOrgName(settleOrg.getOrgName());
            }
            detailVo.setOrder(orderVo);

            //投保人信息
            List<ImcOrderPerson> applicantPersons = this.getOrderPersons(orderId, OrderPersonTypeEnum.A);
            List<OrderPersonVo> applicants = new ArrayList<>();
            applicantPersons.parallelStream().forEach(
                    applicant -> {
                        OrderPersonVo personVo = new OrderPersonVo();
                        BeanUtils.copyProperties(applicant, personVo);
                        applicants.add(personVo);
                    }
            );
            detailVo.setApplicants(applicants);

            //被保人信息
            List<ImcOrderPerson> insurantPersons = this.getOrderPersons(orderId, OrderPersonTypeEnum.B);
            List<OrderPersonVo> insurants = new ArrayList<>();
            insurantPersons.parallelStream().forEach(
                    insurant -> {
                        OrderPersonVo personVo = new OrderPersonVo();
                        BeanUtils.copyProperties(insurant, personVo);
                        insurants.add(personVo);
                    }
            );
            detailVo.setInsurants(insurants);

            //受益人信息
            List<ImcOrderPerson> favoursPersons = this.getOrderPersons(orderId, OrderPersonTypeEnum.C);
            List<OrderPersonVo> favours = new ArrayList<>();
            favoursPersons.parallelStream().forEach(
                    favour -> {
                        OrderPersonVo personVo = new OrderPersonVo();
                        BeanUtils.copyProperties(favour, personVo);
                        favours.add(personVo);
                    }
            );
            detailVo.setFavours(favours.stream().sorted(Comparator.comparing(OrderPersonVo::getId)).collect(Collectors.toList()));

            //银行卡查询
            QueryWrapper<ImcOrderBankInfo> bankQueryWrapper = new QueryWrapper<>();
            bankQueryWrapper.eq("order_id", orderId);
            bankQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
            List<ImcOrderBankInfo> orderBankInfos = this.imcOrderBankInfoMapper.selectList(bankQueryWrapper);
            OrderBankInfoVo bankInfoVo = null;
            if (orderBankInfos.size() > 0) {
                bankInfoVo = new OrderBankInfoVo();
                BeanUtils.copyProperties(orderBankInfos.get(0), bankInfoVo);
            } else {
                bankInfoVo = new OrderBankInfoVo();
            }
            detailVo.setBankInfo(bankInfoVo);

            //险种查询
            List<OrderRiskVo> allRisks = this.imcOrderRiskMapper.selectOrderRisksList(orderId, null, SecurityUtils.getTenantId(), new RenewalOrderSearchForm());
            //首年险种
            List<OrderRiskVo> risks = allRisks.stream().filter(s -> s.getPolicyYear() == 1).collect(Collectors.toList());
            //续期险种
            List<OrderRiskVo> renewalRisks = allRisks.stream().filter(s -> s.getPolicyYear() != 1).collect(Collectors.toList());
            detailVo.setRisks(risks);
            detailVo.setRenewalRisks(renewalRisks);

            //影像件查询
            QueryWrapper<ImcOrderImg> imgQueryWrapper = new QueryWrapper<>();
            imgQueryWrapper.eq("order_id", orderId);
            imgQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
            List<ImcOrderImg> orderImgs = this.imcOrderImgMapper.selectList(imgQueryWrapper);
            List<OrderImgVo> imgs = new ArrayList<>();
            orderImgs.parallelStream().forEach(
                    img -> {
                        OrderImgVo imgVo = new OrderImgVo();
                        BeanUtils.copyProperties(img, imgVo);
                        imgs.add(imgVo);
                    }
            );
            detailVo.setImgs(imgs);

        } else {
            logger.info("保单数据权限异常：{}---{}", SecurityUtils.getTenantId(), order.getTenantId());
            throw new BusinessException("无该保单数据权限");
        }
        return detailVo;
    }

    //获取保单人员列表
    private List<ImcOrderPerson> getOrderPersons(Long orderId, OrderPersonTypeEnum orderPersonTypeEnum) {
        QueryWrapper<ImcOrderPerson> personQueryWrapper = new QueryWrapper<>();
        personQueryWrapper.eq("order_id", orderId);
        personQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        personQueryWrapper.orderByAsc("id");
        if (orderPersonTypeEnum != null) {
            personQueryWrapper.eq("order_person_type", orderPersonTypeEnum.getCode());
        }
        return this.imcOrderPersonMapper.selectList(personQueryWrapper);
    }

    //根据保单id校验保单
    private ImcOrder checkOrderByOrderId(Long orderId) {
        ImcOrder order = this.imcOrderMapper.selectById(orderId);
        Assert.isNull(order, "保单不存在");
        if (!SecurityUtils.getTenantId().equals(order.getTenantId())) {
            throw new BusinessException("当前账号没有权限访问和操作该保单");
        }
        return order;
    }

    /**
     * 查询预收报表分页列表
     *
     * @return 保单集合
     */
    @Override
    public List<ReportAdvanceVo> selectAdvanceReportList(ReportAdvanceForm reportAdvanceForm) {
        logger.info("预收报表查询，参数：{}", reportAdvanceForm.toString());
        return this.imcOrderMapper.selectAdvanceReportList(reportAdvanceForm, SecurityUtils.getTenantId());
    }

    /**
     * 保单转移
     *
     * @param brokerId 转给代理人ID为brokerId的人
     * @param orderIds 要转移的保单id
     * @return
     */
    @Override
    @Transactional
    public int transferOrder(Long brokerId, List<Long> orderIds) {
        if (orderIds.size() == 0) {
            throw new BusinessException("");
        }
        QueryWrapper<ImcOrder> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.in("id", orderIds);
        orderQueryWrapper.in("tenant_id", SecurityUtils.getTenantId());
        List<ImcOrder> list = this.imcOrderMapper.selectList(orderQueryWrapper);
        String username = SecurityUtils.getUsername();
        Date date = DateUtils.getNowDate();
        int count = 0;
        for (ImcOrder order : list) {
            order.setBrokerId(brokerId);
            order.setUpdateId(username);
            order.setUpdateTime(date);
            count += this.imcOrderMapper.updateById(order);
        }
        return count;
    }

    /**
     * REST服务保存保单
     *
     * @param orderDto 保单数据
     * @return
     */
    @Override
    @Transactional
    public int receiveOrder(OrderDto orderDto) {
        logger.info("接收rest保单数据，数据：{}", orderDto.toString());
        Date date = DateUtils.getNowDate();

        OrderForm orderForm = new OrderForm();
        BeanUtils.copyProperties(orderDto.getBasic(), orderForm);
        OrderBankInfoForm bankInfoForm = new OrderBankInfoForm();
        BeanUtils.copyProperties(orderDto.getBankInfo(), bankInfoForm);
        List<OrderPersonForm> applicantForms = MyBeanUtils.copyListProperties(orderDto.getApplicants(), OrderPersonForm::new);
        List<OrderPersonForm> insurantForms = MyBeanUtils.copyListProperties(orderDto.getInsurants(), OrderPersonForm::new);
        List<OrderPersonForm> favourForms = MyBeanUtils.copyListProperties(orderDto.getFavours(), OrderPersonForm::new);
        List<OrderRiskInputForm> riskForms = MyBeanUtils.copyListProperties(orderDto.getProducts(), OrderRiskInputForm::new);
        List<OrderImgForm> imgForms = MyBeanUtils.copyListProperties(orderDto.getImgs(), OrderImgForm::new);
        //基本信息
        ImcOrder order = new ImcOrder();
        BeanUtils.copyProperties(orderForm, order);

        //获取校验租户信息
        QueryWrapper<ImcTenant> tenantQueryWrapper = new QueryWrapper<>();
        tenantQueryWrapper.eq("tenant_guid", orderDto.getTenantKey());
        tenantQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        ImcTenant tenant = this.imcTenantMapper.selectOne(tenantQueryWrapper);
        Assert.isNull(tenant, "非法的渠道码");

        //获取校验供应商信息
        QueryWrapper<ImcRepoSupplier> supplierQueryWrapper = new QueryWrapper<>();
        supplierQueryWrapper.like("supplier_name", orderDto.getBasic().getSupplierName());
        supplierQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        List<ImcRepoSupplier> suppliers = this.imcRepoSupplierMapper.selectList(supplierQueryWrapper);
        if (suppliers.size() > 0) {
            order.setRepoSupplierId(suppliers.get(0).getId());
        } else {
            throw new BusinessException("系统查无此保险公司名称[" + orderDto.getBasic().getSupplierName() + "]");
        }

        //保单号/投保单号校验
        if (checkPolicyCodeUnique(order.getPolicyCode(), null, tenant.getId())) {
            throw new BusinessException("保单号[ " + order.getPolicyCode() + " ]已存在");
        }
        if (checkProposalCodeCodeUnique(order.getProposalCode(), null, tenant.getId())) {
            throw new BusinessException("投保单号[ " + order.getProposalCode() + " ]已存在");
        }
        //代理人信息处理
        ImcBroker broker = this.imcBrokerMapper.selectImcBrokerByCode(orderDto.getBasic().getBrokerCode(), tenant.getId());
        Assert.isNull(broker, "代理人工号在该租户内不存在");
        //初始出单代理人
        order.setBrokerId(broker.getId());
        order.setInitBrokerId(order.getBrokerId());
        ImcTeam team = this.imcTeamMapper.selectById(broker.getTeamId());
        order.setInputOrgId(team.getOrgId());
        //确定保单状态
        if (order.getInsureDate() == null) {
            order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_10.getCode());
        } else {
            order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_20.getCode());
        }
        order.setAckDate(null);
        order.setCustAckDate(null);
        this.orderSave(order, date, tenant.getId(), "api");//保存保单主表信息

        //投保人/被保人/受益人
        this.personSave(applicantForms, insurantForms, favourForms, order, OperationEnum.SAVE, date);

        //影像件
        this.imgSave(imgForms, order, date);

        //银行信息
        this.bankInfoSave(bankInfoForm, order, date);

        //校验转换inscode为ID
        for (OrderRiskInputForm risk : riskForms) {
            ImcRepoIns ins = this.imcRepoInsMapper.getImcRepoInsByInsCode(risk.getInsCode(), order.getRepoSupplierId());
            Assert.isNull(ins, "[" + orderDto.getBasic().getSupplierName() + "]不存在险种编码为[" + risk.getInsCode() + "]的险种");
            risk.setRepoInsId(ins.getId());
            OrderRiskForm riskForm = new OrderRiskForm();
            BeanUtils.copyProperties(risk, riskForm);
            riskForm.setInputOrgId(order.getInputOrgId());
            risk.setApplyDate(order.getApplyDate());
            OrderRiskRateVo vo = this.imcInsRateService.getRates(riskForm);

            if (!vo.isHasStandRate() || !vo.isHasCommissionRate()) {
                throw new BusinessException("险种编码为[ " + risk.getInsCode() + " ]的产品未查询到折标率或佣金率信息");
            }

            risk.setStandRate(vo.getStandRate());
            risk.setCommissionRate(vo.getCommissionRate());
            risk.setSupplierStandRate(vo.getSupplierStandRate());
            risk.setYearScale(vo.getYearScale());
        }
        //险种信息
        this.riskSave(riskForms, order, date);

        //主表更新
        order.setUpdateTime(date);
        return this.imcOrderMapper.updateById(order);
    }

    //根据保单号查询唯一保单
    private ImcOrder checkOrderBypolicyCode(String policyCode, Long tenantId) {
        QueryWrapper<ImcOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("policy_code", policyCode);
        wrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        wrapper.eq("tenant_id", tenantId);
        ImcOrder order = this.imcOrderMapper.selectOne(wrapper);
        Assert.isNull(order, "保单不存在");
        return order;
    }

    /**
     * 保单撤销
     *
     * @param orderCancelDto
     */
    @Override
    public void ApiCancelImcOrder(OrderEndCancelSuspensionDto orderCancelDto) {
        logger.info("API保单撤销操作：{}", orderCancelDto.toString());
        Assert.isNull(orderCancelDto.getPolicyCode(), "policyCode不允许为空，无法与保单关联");
        //获取校验租户信息
        QueryWrapper<ImcTenant> tenantQueryWrapper = new QueryWrapper<>();
        tenantQueryWrapper.eq("tenant_guid", orderCancelDto.getTenantKey());
        tenantQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        ImcTenant tenant = this.imcTenantMapper.selectOne(tenantQueryWrapper);
        Assert.isNull(tenant, "非法的渠道码");

        ImcOrder order = this.checkOrderBypolicyCode(orderCancelDto.getPolicyCode(), tenant.getId());

        order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_30.getCode());
        order.setCancelDate(DateUtils.getNowDate());
        order.setCancelCauseNote(orderCancelDto.getCancelCauseNote());
        order.setPolicyCode("CX:" + orderCancelDto.getPolicyCode());
        order.setProposalCode("CX:" + order.getProposalCode());
        order.setUpdateId("API");
        order.setUpdateTime(DateUtils.getNowDate());

        this.imcOrderMapper.updateById(order);

        //险种状态更新
        this.apiUpdateRiskStatusCode(order.getId(), order.getOrderStatusCode());
    }

    /**
     * 保单终止
     *
     * @param orderEndDto
     */
    @Override
    public void ApiEndImcOrder(OrderEndCancelSuspensionDto orderEndDto) {
        logger.info("api保单终止操作：{}", orderEndDto.toString());
        //获取校验租户信息
        QueryWrapper<ImcTenant> tenantQueryWrapper = new QueryWrapper<>();
        tenantQueryWrapper.eq("tenant_guid", orderEndDto.getTenantKey());
        tenantQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        ImcTenant tenant = this.imcTenantMapper.selectOne(tenantQueryWrapper);
        Assert.isNull(tenant, "非法的渠道码");

        ImcOrder order = this.checkOrderBypolicyCode(orderEndDto.getPolicyCode(), tenant.getId());
        order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_40.getCode());
        if (orderEndDto.getEndCause().equals(EndCauseEnum.A.name())) {
            order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_30.getCode());
            order.setCancelDate(orderEndDto.getEndDate());
            order.setCancelCauseNote(orderEndDto.getEndCauseNote());
        }
        order.setEndDate(orderEndDto.getEndDate());
        order.setEndCause(orderEndDto.getEndCause());
        order.setEndCauseNote(orderEndDto.getEndCauseNote());
        order.setUpdateId("API");
        order.setUpdateTime(DateUtils.getNowDate());
        this.imcOrderMapper.updateById(order);

        //险种状态更新
        this.apiUpdateRiskStatusCode(order.getId(), order.getOrderStatusCode());
    }

    /**
     * 中止
     *
     * @param orderSusDto
     */
    @Override
    public void ApiSuspensionImcOrder(OrderEndCancelSuspensionDto orderSusDto) {
        logger.info("api保单中止操作：{}", orderSusDto.toString());
        //获取校验租户信息
        QueryWrapper<ImcTenant> tenantQueryWrapper = new QueryWrapper<>();
        tenantQueryWrapper.eq("tenant_guid", orderSusDto.getTenantKey());
        tenantQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        ImcTenant tenant = this.imcTenantMapper.selectOne(tenantQueryWrapper);
        Assert.isNull(tenant, "非法的渠道码");

        ImcOrder order = this.checkOrderBypolicyCode(orderSusDto.getPolicyCode(), tenant.getId());
        order.setOrderStatusCode(OrderStatusCodeEnum.STATUS_50.getCode());

        order.setSuspensionDate(orderSusDto.getSuspensionDate());
        order.setSuspensionCause(orderSusDto.getSuspensionCause());
        order.setUpdateId("API");
        order.setUpdateTime(DateUtils.getNowDate());
        this.imcOrderMapper.updateById(order);

        //险种状态更新
        this.apiUpdateRiskStatusCode(order.getId(), order.getOrderStatusCode());
    }

    /**
     * 回执回访告知书
     *
     * @param orderRrcDto
     */
    @Override
    public void apiReceiptRevisitCustom(OrderReceiptRevisitCustomDto orderRrcDto) {
        logger.info("API保单回访操作：{}", orderRrcDto.toString());
        //获取校验租户信息
        QueryWrapper<ImcTenant> tenantQueryWrapper = new QueryWrapper<>();
        tenantQueryWrapper.eq("tenant_guid", orderRrcDto.getTenantKey());
        tenantQueryWrapper.eq("is_deleted", IsDeletedEnum.N.getCode());
        ImcTenant tenant = this.imcTenantMapper.selectOne(tenantQueryWrapper);
        Assert.isNull(tenant, "非法的渠道码");

        ImcOrder order = this.checkOrderBypolicyCode(orderRrcDto.getPolicyCode(), tenant.getId());


        //回访
        order.setRevisitDate(orderRrcDto.getRevisitDate());

        //回执
        order.setAckDate(orderRrcDto.getAckDate());
        order.setCustAckDate(orderRrcDto.getCustAckDate());

        //告知书
        order.setCustomNotifiedDate(orderRrcDto.getCustomNotifiedDate());
        order.setCustomNotifiedUrl(orderRrcDto.getCustomNotifiedUrl());

        order.setUpdateTime(DateUtils.getNowDate());
        order.setUpdateId("API");
        imcOrderMapper.updateById(order);
    }

    @Override
    public List<OrderSelfHoldVo> selfHoldList(OrderSelfHoldForm orderSelfHoldForm) {
        return imcOrderMapper.selfHoldList(orderSelfHoldForm, SecurityUtils.getTenantId());
    }

    /**
     * 标记自保件
     *
     * @param ids
     * @param isSelf
     */
    @Override
    public void updateSelfHold(List<Long> ids, String isSelf) {
        ImcOrder imcOrder = new ImcOrder();
        for (Long id : ids) {
            imcOrder.setId(id);
            imcOrder.setIsSelf(isSelf);
            imcOrder.setUpdateId(SecurityUtils.getUsername());
            imcOrder.setUpdateTime(DateUtils.getNowDate());
            imcOrderMapper.updateById(imcOrder);
        }
    }

    @Override
    public void deleteOrderCheck(Long orderId) {
        StringBuffer errorSb = new StringBuffer();
        QueryWrapper<ImcOrder> orderQW = new QueryWrapper<>();
        orderQW.eq("id", orderId);
        orderQW.eq("is_deleted", IsDeletedEnum.N.getCode());
        orderQW.eq("tenant_id", SecurityUtils.getTenantId());
        List<ImcOrder> orderList = imcOrderMapper.selectList(orderQW);
        Map<Long, String> orderMap = orderList.stream().collect(Collectors.toMap(ImcOrder::getId, ImcOrder::getProposalCode));
        //是否结算，是否发佣，结算月份，发佣月份
        QueryWrapper<ImcOrderRisk> qw = new QueryWrapper<>();
        qw.eq("order_id", orderId);
        qw.eq("is_deleted", IsDeletedEnum.N.getCode());
        qw.eq("tenant_id", SecurityUtils.getTenantId());
        qw.isNotNull("pay_date");
        qw.isNotNull("settle_month");
        qw.eq("is_comm_paid", "Y");
        qw.eq("is_fee_settled", "Y");
        List<ImcOrderRisk> orderRisks = imcOrderRiskMapper.selectList(qw);
        if (!CollectionUtils.isEmpty(orderRisks)) {
            for (ImcOrderRisk orderRisk : orderRisks) {
                errorSb.append("投保单号[").append(orderMap.get(orderRisk.getOrderId())).append("]状态已结算，已发佣，请勿删除");
            }
        }
        //在手续费流程中的保单不能删除
        ImcRecnDetails details = new ImcRecnDetails();
        details.setOrderId(orderId);
        List<ImcRecnDetails> imcRecnDetails = recnDetailsMapper.selectImcRecnDetailsList(details);
        if (!CollectionUtils.isEmpty(imcRecnDetails)) {
            errorSb.append("投保单号[").append(orderMap.get(orderId)).append("]存在手续费流程中，请勿删除");
        }
        if (errorSb.length() > 0) {
            throw new BusinessException(errorSb.toString());
        }
    }

    @Override
    public void deleteOrder(Long orderId) {
        //删除imc_order imc_order_bank_info imc_order_img imc_order_person imc_order_risk
        ImcOrder imcOrder = new ImcOrder();
        imcOrder.setIsDeleted(String.valueOf(orderId));
        UpdateWrapper<ImcOrder> orderWrapper = new UpdateWrapper<>();
        orderWrapper.eq("id", orderId);
        imcOrderMapper.update(imcOrder, orderWrapper);

        QueryWrapper<ImcOrderPerson> personQueryWrapper = new QueryWrapper<>();
        personQueryWrapper.eq("order_id", orderId);
        List<ImcOrderPerson> personList = imcOrderPersonMapper.selectList(personQueryWrapper);
        for (ImcOrderPerson imcOrderPerson : personList) {
            imcOrderPerson.setIsDeleted(String.valueOf(imcOrderPerson.getId()));
            imcOrderPersonMapper.updateById(imcOrderPerson);
        }

        QueryWrapper<ImcOrderBankInfo> bankInfoQueryWrapper = new QueryWrapper<>();
        bankInfoQueryWrapper.eq("order_id", orderId);
        List<ImcOrderBankInfo> bankInfoList = imcOrderBankInfoMapper.selectList(bankInfoQueryWrapper);
        for (ImcOrderBankInfo bankInfo : bankInfoList) {
            bankInfo.setIsDeleted(String.valueOf(bankInfo.getId()));
            imcOrderBankInfoMapper.updateById(bankInfo);
        }


        QueryWrapper<ImcOrderImg> imgQueryWrapper = new QueryWrapper<>();
        imgQueryWrapper.eq("order_id", orderId);
        List<ImcOrderImg> imgList = imcOrderImgMapper.selectList(imgQueryWrapper);
        for (ImcOrderImg img : imgList) {
            img.setIsDeleted(String.valueOf(img.getId()));
            imcOrderImgMapper.updateById(img);
        }


        QueryWrapper<ImcOrderRisk> riskQueryWrapper = new QueryWrapper<>();
        riskQueryWrapper.eq("order_id", orderId);
        List<ImcOrderRisk> riskList = imcOrderRiskMapper.selectList(riskQueryWrapper);
        for (ImcOrderRisk risk : riskList) {
            risk.setIsDeleted(String.valueOf(risk.getId()));
            imcOrderRiskMapper.updateById(risk);
        }
    }

    /**
     * 保单详情查询
     *
     * @param orderId
     * @return
     */
    @Override
    public ImcOrder selectImcOrderByOrderId(Long orderId) {
        return imcOrderMapper.selectById(orderId);
    }

    @Override
    public List<ReportAdvanceExportVo> advanceAllExport(ReportAdvanceForm reportAdvanceForm) {
        logger.info("预收报表导出，参数：{}", reportAdvanceForm.toString());
        return this.imcOrderMapper.selectAdvanceReportExportList(reportAdvanceForm, SecurityUtils.getTenantId());
    }
}
